package org.deng.vertx.common.util;


import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Clock;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultClock;

/**
 * @Project
 * @Module
 * @JDK_Vserion 1.8
 * @Author DengLibin
 * @Email dlb@smarthse.cn
 * @Desc
 * @since 2020/3/17 0017 22:26
 */
public class JwtUtil {
	
    private  static final String secret = "OSus39Y6s2j9suSA";
    
    private static Long admin_expiration =  24 * 60 * 60 * 1000L; //毫秒, 后台token有效期1天

    
    private  static Clock clock = DefaultClock.INSTANCE;
    
    /**
     * 生成token(有效时间默认1天)
     */
    public static String generateToken(String subject) {
        Map<String, Object> claims = new HashMap<>();
        return doGenerateToken(claims, subject);
    }
    

    
    public static String getSubjectFromToken(String token) {

        try{
            return getClaimFromToken(token, Claims::getSubject);

        }catch (Exception e){
            e.printStackTrace();
        }
        return null;

    }
    
    /**
     * 获取账号id
     */
    public static Long getUserIdFromToken(String token) {
    	
    	if (token == null || token.isEmpty()) return null;
    	
        String s =  getClaimFromToken(token, Claims::getSubject);
        if(s == null){
            return null;
        }
        return Long.parseLong(s);
    }
    
    /**
     * 获取账号类型(cn.smarthse.serve.common.model.RoleEnum)
     */
    public static Integer getTypeFromToken(String token) {
    	
        Claims claims = null;
		try {
			claims = getAllClaimsFromToken(token);
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
        
        Integer type = claims.get("type", Integer.class);
		return claims == null || type == null ? 0 : type;
    }
    
    /**
     * 获取账号昵称
     */
    public static String getNicknameFromToken(String token) {
    	
    	if (token == null || token.isEmpty()) return null;
    	
        Claims claims = getAllClaimsFromToken(token);
        
		return claims == null ? null : claims.get("nickname", String.class);
    }
    
    /**
     * 判断token是否过期
     */
    public static boolean isTokenExpired(String token) {
    	
    	if (token == null || token.isEmpty()) return true;
    	
        final Date expiration = getExpirationDateFromToken(token);
        return expiration == null || expiration.before(clock.now());
    }
    
    /**
     * 获取过期时间
     */
    public static Date getExpirationDateFromToken(String token) {
    	
        return getClaimFromToken(token, Claims::getExpiration);
    }
    
    /**
     * 生成token
     */
    private static String doGenerateToken(Map<String, Object> claims, String subject) {
        final Date createdDate = clock.now();
        final Date expirationDate = calculateExpirationDate(createdDate);
        
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(subject)
                .setIssuedAt(createdDate)
                .setExpiration(expirationDate)
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }
    
    /**
     * 计算出过期时间
     */
    private static Date calculateExpirationDate(Date createdDate) {
        return new Date(createdDate.getTime() + admin_expiration);
    }
    
    /**
     * 计算出过期时间
     */
    private static Date calculateExpirationDate(Date createdDate, Long expiration) {
        return new Date(createdDate.getTime() + expiration);
    }
    
    private static <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {

        try{
            final Claims claims = getAllClaimsFromToken(token);
            return claimsResolver.apply(claims);
        }catch (Exception e){
            return null;
        }
    }

    private static Claims getAllClaimsFromToken(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }
}
